﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Xml;

using CSInteropSign;
using System.Security.Cryptography;

namespace ProShoppingPen {
    public partial class FrmShoppingPen : Form {

        public const int USER = 0x1500;
        public const int WM_COPYDATA = 0x004A;
        public const int WM_POLLING_RESPONSE = 0x0400 + 0x03;

        public const int BLOCK_SIZE = 50;
        public const int ID_LEN = 6;
        public const int HEADER_LEN = 40;
        public const string PUBLIC_KAY = "publickey.der";

        string autoUpdate, defaultBrowser, popHome;

        private DateTime _lastTime, _curTime;
        private int relayTime = 5000;
        private bool isCatchRestart = false;

        private string _penID = null;
        public FrmShoppingPen () {
            InitializeComponent( );
        }


        // <summary>
        /// 发送 WM_COPYDATA 消息的数据结构体
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct COPYDATASTRUCT {
            /// <summary>
            /// 用户自定义数据
            /// </summary>
            public IntPtr dwData;
            /// <summary>
            /// 数据长度
            /// </summary>
            public int cbData;
            /// <summary>
            /// 数据地址指针
            /// </summary>
            public IntPtr lpData;
        }

        /// <summary>
        /// 获取消息类型为 WM_COPYDATA 中的数据
        /// </summary>
        /// <param name="m"></param>
        /// <param name="dwData"> 附加数据 </param>
        /// <param name="lpdata"> 接收到的发送数据 </param>
        public static void ReceivCopyData ( ref Message m, out int dwData, out byte[ ] lpdata ) {
            COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
            dwData = cds.dwData.ToInt32( );
            lpdata = new byte[cds.cbData];
            Marshal.Copy(cds.lpData, lpdata, 0, cds.cbData);
            m.Result = (IntPtr)0;
        }

        protected override void DefWndProc ( ref System.Windows.Forms.Message m ) {

            switch (m.Msg) {

                case WM_POLLING_RESPONSE:

                   // lblTime.Text = DateTime.Now.ToString( );
                    _lastTime = DateTime.Now;
                    break;

                case WM_COPYDATA:

                    int dwData;
                    byte[ ] lpData;
                    ReceivCopyData(ref m, out dwData, out lpData);

                    ASCIIEncoding encoding = new ASCIIEncoding( );
                    switch(dwData){   //判断当前是什么类型的处理

                        case 0:



                            string constructedString = encoding.GetString(lpData);
                            string urlStr = constructedString.Replace("\0", "");
                            lablMessage.Text = "解码结果为：" + urlStr;
                            
                            string URL;
                            URL = GetNewURL(urlStr); //打开IE

                            if (!defaultBrowser.Equals("1"))
                                OpenURL(URL, false);
                            else
                                OpenURL(URL, true);



                            break;
                        case 1:
                            /*     try {
                                     byte[ ] id = new byte[ID_LEN];
                                     byte[ ] sigBuf = new byte[BLOCK_SIZE];

                                     if (lpData != null) {

                                         System.Array.Copy(lpData, 0, id, 0, ID_LEN);
                                         System.Array.Copy(lpData, 6, sigBuf, 0, BLOCK_SIZE);
                                         if (VerifyDsaMessage(PUBLIC_KAY, id, sigBuf)) {
                                             _penID = DecToString(id, ID_LEN);
                                         }
                                         relayTime = 1500;  //解码线程 活动检测时间间隔
                                         if (isCatchRestart) {
                                             isCatchRestart = false;
                                             break;

                                         }

                                             if (popHome.Equals("1")) {
                                                 string homePageURL;
                                                 homePageURL = GetURL("0"); //打开IE

                                                 if (defaultBrowser.Equals("1")) {
                                                     if (!defaultBrowser.Equals("1"))
                                                         OpenURL(homePageURL, false);
                                                     else
                                                         OpenURL(homePageURL, true);
                                                 }


                                             }
                                             toolStripStatusLabelState.Text = "当前状态：点读笔已插入";
                                             //最小化到状态栏图标
                                             //  if (this.WindowState == FormWindowState.Normal) {
                                             this.Visible = false;//隐藏窗体
                                             this.notifyIcon.Visible = true;//显示托盘图标
                                             this.notifyIcon.Text = this.Text;//设置托盘文本


                                     }
                                 }
                                 catch {
                                     toolStripStatusLabelState.Text = "当前状态：点读笔初始化失败";
                                     break;
                                 }*/
                            relayTime = 1500;  //解码线程 活动检测时间间隔
                            if (isCatchRestart) {
                                isCatchRestart = false;
                                break;

                            }
                            try{
                                lablMessage.Text = "解码结果为：1";
                                if (popHome.Equals("1")) {
                                    string homePageURL;
                                    homePageURL = GetNewURL("1"); //打开IE

                                    if (defaultBrowser.Equals("1")) {
                                        if (!defaultBrowser.Equals("1"))
                                            OpenURL(homePageURL, false);
                                        else
                                            OpenURL(homePageURL, true);
                                    }


                                }
                                toolStripStatusLabelState.Text = "当前状态：点读笔已插入";
                                //最小化到状态栏图标
                                //  if (this.WindowState == FormWindowState.Normal) {
                                this.Visible = false;//隐藏窗体
                                this.notifyIcon.Visible = true;//显示托盘图标
                                this.notifyIcon.Text = this.Text;//设置托盘文本
                            }
                            catch {
                                toolStripStatusLabelState.Text = "当前状态：点读笔初始化失败";
                                break;
                            }
                            break;
                        case 2:

                            toolStripStatusLabelState.Text = "当前状态：点读笔拔出";

                            //显示窗体

                                this.Visible = true;
                                this.Left = this.Left;
                                this.WindowState = FormWindowState.Normal;
                                this.notifyIcon.Visible = false;

                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    base.DefWndProc(ref m);
                    break;
            }
        }


        private static bool VerifyDsaMessage ( string p, byte[ ] message, byte[ ] signature ) {

            // convert signature to p1363
            // see http://www.codeproject.com/KB/security/CryptoInteropSign.aspx

            signature = convertP1363(signature);

            //
            // Load the Public Key
            //   X.509 Format
            //
            AsnKeyParser keyParser = new AsnKeyParser(p);


            DSAParameters publicKey = keyParser.ParseDSAPublicKey( );

            //
            // Initailize the CSP
            //
            CspParameters csp = new CspParameters( );

            // Cannot use PROV_DSS_DH
            const int PROV_DSS = 3;
            csp.ProviderType = PROV_DSS;

            const int AT_SIGNATURE = 2;
            csp.KeyNumber = AT_SIGNATURE;

            csp.KeyContainerName = "DSA Test (OK to Delete)";

            //
            // Initialize the Provider
            //
            DSACryptoServiceProvider dsa =
              new DSACryptoServiceProvider(csp);
            dsa.PersistKeyInCsp = false;

            //
            // The moment of truth...
            //
            dsa.ImportParameters(publicKey);



            //
            // Compute h(m)
            //
            SHA1 sha = new SHA1CryptoServiceProvider( );
            byte[ ] hash = sha.ComputeHash(message);

            //
            // Initialize Verifier
            //
            DSASignatureDeformatter verifier =
              new DSASignatureDeformatter(dsa);
            verifier.SetHashAlgorithm("SHA1");

            bool verify = (verifier.VerifySignature(hash, signature));

            // See http://blogs.msdn.com/tess/archive/2007/10/31/
            //   asp-net-crash-system-security-cryptography-cryptographicexception.aspx
            dsa.Clear( );

            return verify;

        }

        private static byte[ ] convertP1363 ( byte[ ] signature ) {
            AsnParser asn = new AsnParser(signature);
            asn.NextSequence( );
            byte[ ] r = asn.NextInteger( );
            byte[ ] s = asn.NextInteger( );

            // Returned to caller
            byte[ ] p1363Signature = new byte[40];

            if (r.Length > 21 || (r.Length == 21 && r[0] != 0)) {
                throw new Exception("Error p1363");
                // WTF???
                // Reject - signature verification failed
            } else if (r.Length == 21) {
                // r[0] = 0
                // r[1]'s high bit *should* be set
                Array.Copy(r, 1, p1363Signature, 0, 20);
            } else if (r.Length == 20) {
                // r[0]'s high bit *should not* be set
                Array.Copy(r, 0, p1363Signature, 0, 20);
            } else {
                // fewer than 20 bytes
                int len = r.Length;
                int off = 20 - len;
                Array.Copy(r, 0, p1363Signature, off, len);
            }

            // Do the same for s
            // Copy s into p1363Signature starting at offset 20 of p1363Signature
            // ...
            if (s.Length > 21 || (s.Length == 21 && s[0] != 0)) {
                throw new Exception("Error p1363");
                // WTF???
                // Reject - signature verification failed
            } else if (s.Length == 21) {
                // r[0] = 0
                // r[1]'s high bit *should* be set
                Array.Copy(s, 1, p1363Signature, 20, 20);
            } else if (s.Length == 20) {
                // r[0]'s high bit *should not* be set
                Array.Copy(s, 0, p1363Signature, 20, 20);
            } else {
                // fewer than 20 bytes
                int len = s.Length;
                int off = 40 - len;
                Array.Copy(s, 0, p1363Signature, off, len);
            }

            return p1363Signature;
        }

        public string HexToString ( byte[ ] buf, int len ) {
            string Data1 = "";
            string sData = "";
            int i = 0;
            while (i < len) {
                //Data1 = String.Format(”{0:X}”, buf[i++]); //no joy, doesn’t pad
                Data1 = buf[i++].ToString("X").PadLeft(2, '0'); //same as “%02X” in C
                sData += Data1;
            }
            return sData;
        }

        public string DecToString ( byte[ ] buf, int len ) {
            string Data1 = "";
            string sData = "";
            int i = 0;
            while (i < len) {
                //Data1 = String.Format(”{0:X}”, buf[i++]); //no joy, doesn’t pad
                Data1 = buf[i++].ToString("D"); //same as “%02X” in C
                sData += Data1;
            }
            return sData;
        }

        private void RunExApplication ( string appName ) {

            Process mPro = new Process( );
            string path = System.AppDomain.CurrentDomain.BaseDirectory;
            mPro.StartInfo.FileName = path + "\\" + appName;
            mPro.Start( );

        }


        //打开指定URL的网页，defBrowser =true为默认浏览器，否则为IE浏览器
        private void OpenURL ( string URL, bool defBrowser ) {

        //    if (_penID == null)
       //         return;
            if (!defBrowser) {
                //调用IE
                System.Diagnostics.Process myProcess = new System.Diagnostics.Process( );
                myProcess.StartInfo.FileName = "iexplore.exe";
                myProcess.StartInfo.Arguments = URL;
                myProcess.Start( );
            } else {

                //调用默认浏览器: 
                try {
                    System.Diagnostics.Process.Start(URL);
                }
                catch (System.ComponentModel.Win32Exception noBrowser) {
                    if (noBrowser.ErrorCode == -2147467259)
                        MessageBox.Show("没有默认浏览器");
                }
                catch (System.Exception other) {
                    MessageBox.Show("此对应链接不存在，请确认！");
                }
            }
        }

        private string GetNewURL(string id){

            long codeID;
            string URL = null;
            string usrPre = null;
            string homePage = null;
            
            if (id == null)
            {
                return URL;
            }

            IniFile iniFileOpt = new IniFile(AppDomain.CurrentDomain.BaseDirectory + "web.ini");
            homePage = iniFileOpt.IniReadValue("web", "homepage");

            codeID = long.Parse(id);

            if (codeID < 11){
                URL = homePage + iniFileOpt.IniReadValue("web", id);
            }
            if ( (codeID>200) && (codeID<301)){
                URL = homePage + iniFileOpt.IniReadValue("web", "201-300") + id;
            }
            if ((codeID >300) && (codeID <1001)){
                URL = homePage + iniFileOpt.IniReadValue("web", "301-1000") + id;
            }
            if ((codeID > 1000) && (codeID < 10001)) {
                URL = homePage + iniFileOpt.IniReadValue("web", "1001-10000") + id;
            }
            if ((codeID > 10000) && (codeID < 50001)) {
                URL = homePage + iniFileOpt.IniReadValue("web", "10001-50000") + id;
            }
            if ((codeID > 50000) && (codeID < 70001)) {
                URL = homePage + iniFileOpt.IniReadValue("web", "50001-70000") + id;
            }
            if ((codeID > 70000) && (codeID < 80001)) {
                URL = homePage + iniFileOpt.IniReadValue("web", "70001-80000") + id;
            }
            if ((codeID > 80000) && (codeID < 90001)) {
                URL = homePage + iniFileOpt.IniReadValue("web", "80001-90000") + id;
            }
            if ((codeID > 100000) && (codeID < 1000000)) {
                URL = homePage + iniFileOpt.IniReadValue("web", ">100001") + id;
            }

            return URL;

        }

        private string GetURL (string id){

            string line;
            string url = "";

            // Read the file and display it line by line.
            System.IO.StreamReader file =
               new System.IO.StreamReader("netPage.txt");
            while ((line = file.ReadLine( )) != null) {

                try
                {
                    if (id.Equals( line.Substring(0,line.IndexOf(" ")) ))
                    {
                        url = line.Substring(line.IndexOf(" ")+1, line.Length - id.Length - 1);
                        url = url.Replace(@"\",@"\\");
                    }
                    
                }
                catch
                {
                    url = "";
                }

            }

            file.Close( );
            return url;

    }
        private void KillProcess ( string processName ) {

            Process[ ] prcs = Process.GetProcesses( );
            foreach (Process p in prcs) {
                if (p.ProcessName.Equals(processName)) {
                    p.Kill( );
                }
            }

        }

        private void LoadIniFileOptions(){
            try
            {
                IniFile iniFileOpt = new IniFile(AppDomain.CurrentDomain.BaseDirectory + "config.ini");

                autoUpdate = iniFileOpt.IniReadValue("config", "autoUpdate");
                defaultBrowser = iniFileOpt.IniReadValue("config", "defaultBrowser");
                popHome = iniFileOpt.IniReadValue("config", "popHome");
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("配置文件丢失！");
                this.Close( );
            }
        }

        private void FrmShoppingPen_FormClosed ( object sender, FormClosedEventArgs e ) {

            KillProcess("vfwcap");
            KillProcess("VFWCAP");
        }

        private void notifyIcon_MouseDoubleClick ( object sender, MouseEventArgs e ) {

 //           if (this.WindowState == FormWindowState.Minimized) {
                this.Visible = true;
                this.Left = this.Left;
                this.WindowState = FormWindowState.Normal;
                this.notifyIcon.Visible = false;
  //          }
        }

        private void QuiteToolStripMenuItem_Click ( object sender, EventArgs e ) {

            Application.Exit( );
        }

        private void FrmShoppingPen_SizeChanged ( object sender, EventArgs e ) {

            if (this.WindowState == FormWindowState.Minimized) {
                this.Visible = false;//隐藏窗体
                this.notifyIcon.Visible = true;//显示托盘图标
                this.notifyIcon.Text = this.Text;//设置托盘文本
            }

        }

        private string GetTheProVersion ( string fileName ) {
            string proVersion = "";
            string AutoUpdaterFileName = fileName;
            if (!File.Exists(AutoUpdaterFileName))
                return proVersion;
            //打开xml文档
            FileStream myFile = new FileStream(AutoUpdaterFileName, FileMode.Open);
            // xml文件阅读器
            XmlTextReader xml = new XmlTextReader(myFile);
            while (xml.Read( )) {
                if (xml.Name == "Version") {
                    // 获取升级文档的最后一次更新日期 
                    proVersion = xml.GetAttribute("Num");
                    break;
                }
            }
            xml.Close( );
            myFile.Close( );
            return proVersion;
        }

        private void RunVfwcapProcess(){

            string appName = "vfwcap.exe"; //运行识别程序
            _vfwProcess = new Process( );
            string path = System.AppDomain.CurrentDomain.BaseDirectory;
            _vfwProcess.StartInfo.FileName = path + "\\" + appName;
            _vfwProcess.Start( );
        }

        private void FrmShoppingPen_Load ( object sender, EventArgs e ) {


            KillProcess("vfwcap");
            KillProcess("VFWCAP");

            //LiveUpdate新程序重命名
            if (File.Exists("PenLiveUpdate_NEW.exe")) {
                if (File.Exists("PenLiveUpdate.exe"))
                    File.Delete("PenLiveUpdate.exe");
                File.Move("PenLiveUpdate_NEW.exe", "PenLiveUpdate.exe");      
            
            }

            string appName = "PenLiveUpdate.exe"; //自动升级程序名字 
            LoadIniFileOptions( ); //读取配置选项

            toolStripStatusLblVersion.Text = GetTheProVersion("AutoUpdater.xml"); //程序当前版本号

            if(autoUpdate.Equals("1"))      //是否自动升级    
                RunExApplication(appName);


            RunVfwcapProcess(); // 运行识别算法程序
            timer1.Enabled = true;
            timer1.Start( );
        }

        private void ToolStripMenuItemAbout_Click ( object sender, EventArgs e ) {
            FrmPenAbout penAbout = new FrmPenAbout( );
            penAbout.ShowDialog( );
        }

        private void toolStripMenuItemQuit_Click ( object sender, EventArgs e ) {
            Application.Exit( );
        }

        private void ToolStripMenuItemCheckPen_Click ( object sender, EventArgs e ) {

            LoadIniFileOptions( );
            KillProcess("vfwcap");
            KillProcess("VFWCAP");
  //          string appName = "vfwcap.exe"; //运行识别程序
   //         RunExApplication(appName);

            RunVfwcapProcess( ); // 运行识别算法程序

        }

        private void ToolStripMenuItemOptions_Click ( object sender, EventArgs e ) {

            FrmOptions fOpentions = new FrmOptions( );
            if (fOpentions.ShowDialog( ) == DialogResult.OK)
                LoadIniFileOptions( );


        }

        private void ToolStripMenuItemLiveUpdate_Click ( object sender, EventArgs e ) {

            string appName = "PenLiveUpdate.exe"; //自动升级程序名字
            if (!autoUpdate.Equals("1"))
            {                
                RunExApplication(appName);
            }else{


                try {
                    IniFile iniFileOpt = new IniFile(AppDomain.CurrentDomain.BaseDirectory + "config.ini");

                    iniFileOpt.IniWriteValue("config", "autoUpdate", "0");

                    Process mLivePro = new Process( );
                    string path = System.AppDomain.CurrentDomain.BaseDirectory;
                    mLivePro.StartInfo.FileName = path + "\\" + appName;
                    mLivePro.Start( );
                    mLivePro.WaitForExit( );

                    iniFileOpt.IniWriteValue("config", "autoUpdate", "1");
                }
                catch (System.Exception ex) {
                    MessageBox.Show("配置文件丢失！");
                    this.Close( );
                }


            }
        }

        private void ToolStripMenuItemShowPro_Click ( object sender, EventArgs e ) {

            //显示窗体

                this.Visible = true;
                this.Left = this.Left;
                this.WindowState = FormWindowState.Normal;
                this.notifyIcon.Visible = false;

        }

        private void RestartVfwcapPor(){

            KillProcess("vfwcap");
            KillProcess("VFWCAP");

            isCatchRestart = true;

            RunVfwcapProcess();
           
        }

        private Process _vfwProcess;
        private void timer1_Tick ( object sender, EventArgs e ) {

            _curTime = DateTime.Now;

            if ((_curTime - _lastTime).TotalMilliseconds > relayTime)
            {
                _lastTime = DateTime.Now;
         //       MessageBox.Show("vfwcap pro error!");
                RestartVfwcapPor( );
               
            }
       

        }

    }
}
